package xaj.scc.util.mapping;

import java.util.ArrayList;
import java.util.List;

public class AddGrammar {
	
	private static AddGrammar instance = null;  
	private String defaultImports = "";
	private List<String> classesImports;
	private String defaultParser = "";
	private List<String> productions;
	private List<String> nonTerminal;
	
	/**
	 * Todos os não terminais devem ser armazenados. A lista de nonTerminal deveria
	 * conter somente os não terminais e não a string "non terminal type name;" 
	*/
	private List<String> nonTerminalList;
	
	public static AddGrammar getInstance(){
		if(instance == null)
			instance = new AddGrammar();
		return instance;
	}
	private AddGrammar(){
		classesImports = new ArrayList();
		productions = new ArrayList();
		nonTerminal = new ArrayList();
		
		//Alterado por Leonardo
		nonTerminalList = new ArrayList<String>();
		
		setDefaultImports( "include"+ " \"aspectj.ppg\"\n\n"+

						"package abc.xaj.parse;\n\n"+
						"import polyglot.ast.*;\n"+
						"import polyglot.lex.*;\n"+
						"import abc.aspectj.ast.*;\n\n"+

						"import java.util.*;\n\n"+

						"import abc.xaj.ast.XAJNodeFactory;\n"+
						"import abc.xaj.types.XAJTypeSystem;\n\n");
		
		setDefaultParser("parser Grm extends abc.aspectj.parse.Grm {:\n"+
				"	public final XAJNodeFactory nf;\n"+
				"	public final XAJTypeSystem ts;\n\n"+
  
				"	public Grm(Lexer l, TypeSystem t, NodeFactory n, ErrorQueue q) {\n"+
				"		super(l, t, n, q);\n"+
				"		nf = (XAJNodeFactory) n;\n"+
				"		ts = (XAJTypeSystem) t;\n"+
				"   }\n"+
				":}\n\n");
		
		
	}
	
	public String getDefaultImports() {
		return defaultImports;
	}
	
	public void setDefaultImports(String defaultImports) {
		this.defaultImports = defaultImports;
	}
	public List<String> getClassesImports() {
		return classesImports;
	}
	public void setClassesImports(List<String> classesImports) {
		this.classesImports = classesImports;
	}
	public String getDefaultParser() {
		return defaultParser;
	}
	public void setDefaultParser(String defaultParser) {
		this.defaultParser = defaultParser;
	}
	public void setProductions(List<String> productions) {
		this.productions = productions;
	}
	
	public List<String> getNonTerminal() {
		return nonTerminal;
	}
	public void setNonTerminal(List<String> nonTerminal) {
		this.nonTerminal = nonTerminal;
	}
	
	public void insertClassesImports(String classes){
		if(!classesImports.contains(classes))
		classesImports.add(classes);
	}
	public void insertProductions(String production){
		if(!productions.contains(production))
			productions.add(production);
	}
	public void insertNonTerminal(String nTerm){
		if(!nonTerminal.contains(nTerm))
			nonTerminal.add(nTerm);
	}
	
	
	public String toString(){
		String imp = "";
		//importa��es padroes
		imp += getDefaultImports();
		
		//importa��es das classes
		imp += "/"+"/"+"importa a classe\n";
		imp += classesImportsToString()+"\n";
		
		// parser
		imp += getDefaultParser();
		
		imp += "/"+"/ ------ new tokens ------------------------------\n\n";
		imp += "/"+"/ ----- new non-terminals ------------------------\n\n";
		imp += nonTerminalToString();
		
		imp +="/"+"/"+" ---- Productions -------------------------------\n"+
		 "\nstart with goal;\n\n";
		imp += productionsToString()+"\n";
		
		return imp;
	}
	//TODO Verificar como e inserido na lista de classesImports,noTerminal,Production para evitar erros
	
	public String classesImportsToString(){
		String clas = "";
		for(Object e:classesImports){
			clas += "import " + e.toString()+";\n";
		}
		return clas;
	}
	
	public String nonTerminalToString(){
		String term = "";
		for(Object e : nonTerminal){
			//term += "non terminal " + e.toString() + "\n";
			term += e.toString()+"\n";
		}
		return term;
	}
	
	public String productionsToString(){
		String prod = "";
		for(Object e:productions){
			prod += e.toString()+"\n";
		}
		return prod;
	}
	
	/**
	 * Métodos adicionados por Leonardo
	 */
	public void addNonTerminal(String nonTerminal) {
		if(!nonTerminalList.contains(nonTerminal))
			nonTerminalList.add(nonTerminal);
	}
	
	public boolean containsNonTermianl(String nonTerminal) {
		return nonTerminalList.contains(nonTerminal);
	}
}
